home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.000
/
crossfir
/
crossfire-0.92.4.client
/
init.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-21
|
11KB
|
421 lines
/* This handles the initialization of the client. This includes making
* the I_IMAGE and I_ARCH commands.
*/
#include <client.h>
/*
* A replacement of strdup(), since it's not defined at some
* unix variants.
*/
char *strdup_local(char *str) {
char *c=(char *)malloc(sizeof(char)*strlen(str)+1);
strcpy(c,str);
return c;
}
void VersionCmd(ArgList msg)
{
if (ECLIENT_VERSION != ArgList_getLong(msg,2)) {
printf("Client, Server have different versions (%d,%ld)\n",
ECLIENT_VERSION,ArgList_getLong(msg,2));
exit(1);
}
}
void SendVersion(TcpSocket conn)
{
ArgList msg;
msg = ArgList_create();
ArgList_addLong(msg,STRINGCOMMAND);
ArgList_addString(msg,"version");
ArgList_addLong(msg,ECLIENT_VERSION);
ArgList_send(conn,msg);
ArgList_destroy(msg);
}
void SendAddMe(TcpSocket conn)
{
ArgList msg;
msg = ArgList_create();
ArgList_addLong(msg,STRINGCOMMAND);
ArgList_addString(msg,"addme");
ArgList_send(conn,msg);
ArgList_destroy(msg);
}
void SendSetFaceMode(TcpSocket conn,int mode)
{
ArgList msg;
msg = ArgList_create();
ArgList_addLong(msg,STRINGCOMMAND);
ArgList_addString(msg,"setfacemode");
ArgList_addChar(msg,mode);
ArgList_send(conn,msg);
ArgList_destroy(msg);
}
#if 0
/* Some config options */
#define MAX_MISSING_FACES 500
#define MAX_MISSING_ARCHS 500
static char missing_archs[MAX_MISSING_ARCHS][40];
static int num_missing_archs=0, on_arch_num=0;
/* This loads up the archetypes that the client uses. We use to
* libcross (../common) routines for most of this.
*
* This is a lot like the load_archetypes routine in the arch.c file. The
* main difference is that we only do one pass - treasures and other
* arch links we don't care about.
*/
void init_client_archetypes()
{
extern int arch_init;
int comp;
char buf[MAX_BUF];
FILE *fp;
arch_init=1;
clear_archetable();
sprintf(buf,"%s/%s", LibDir, ArcheTypes);
if((fp=open_and_uncompress(buf,0,&comp))==NULL) {
LOG(llevError,"Can't open archetype file.\n");
}
else {
first_arch_pass(fp);
close_and_delete(fp, comp);
}
/* If we have a local file, load that now */
if (client_libdir && client_archfile) {
archetype *at = first_archetype, *tmp_arch;
sprintf(buf,"%s/%s", client_libdir, client_archfile);
if((fp=open_and_uncompress(buf,0,&comp))==NULL) {
LOG(llevError,"Can't open archetype file.\n");
}
else {
first_arch_pass(fp);
close_and_delete(fp, comp);
/* the first_arch_passes sets the first_archetype pointer.
* We preserved the previous value, now we need to
* connect the two lists. If at is null, it means that
* there was not a previous first pass - thus, we only
* need to do things when it is not null.
*/
if (at!=NULL) {
tmp_arch = first_archetype;
/* Go to the end of the archetypes we just loaded.
* This should be a shorter list than the standard
* file
*/
while (tmp_arch->next)
tmp_arch=tmp_arch->next;
/* tmp_arch->next is now null. So connect the list */
tmp_arch->next = at;
}
}
}
init_archetable();
arch_init=0;
}
int request_missing_archs(int max_requests)
{
while (on_arch_num<num_missing_archs && pending_archs<max_requests) {
write_socket("REQUEST %s ARCH\n", missing_archs[on_arch_num]);
pending_archs++;
on_arch_num++;
}
if (pending_archs || on_arch_num<num_missing_archs) return 1;
return 0;
}
void add_missing_arch_name(char *buf)
{
strcpy(missing_archs[num_missing_archs++],buf);
}
/* This gets all the image names from the server. It then
* compares it against the list it read in. Any archetypes the
* server has but the client does not are then requested.
*/
void get_arch_names(char *buf)
{
char *cp;
do {
if ((cp = strchr(buf,' '))!=NULL) *cp++='\0';
if (!strcmp(buf,"START")) {
num_missing_archs=0;
on_arch_num=0;
}
else if (!strcmp(buf,"END")) {
int i;
for (i=0; i<num_missing_archs; i++)
printf("missing arch %s\n", missing_archs[i]);
}
else {
if (find_archetype(buf)==NULL) {
add_missing_arch_name(buf);
if (num_missing_archs==MAX_MISSING_ARCHS) {
fprintf(stderr,"Error - too many missing archetypes.\n");
exit(1);
}
}
}
buf = cp;
} while (buf!=NULL);
}
static char missing_faces[MAX_MISSING_FACES][30];
static int num_missing_faces=0, on_face_num=0;
/* This function goes through the missing_faces array and requests
* that the images be sent. It only does a few at a time, so that
* it won't get swamped
* returns TRUE if there is more images to be requested or
* received (pending requests), FALSE if all the images have been requested
* and received. The reason that pending images is checked is so that
* the client does not request more data to be transmitted, thus
* overflowing the server buffers (which will then cause the connection
* to close)
*
*/
int request_missing_images(int max_requests)
{
while (on_face_num<num_missing_faces && pending_images<max_requests) {
write_socket("REQUEST %s %s\n", missing_faces[on_face_num],
(display_mode==Xpm_Display)?"XPM":"BIT");
pending_images++;
on_face_num++;
}
if (pending_images || on_face_num<num_missing_faces) return 1;
return 0;
}
/* This adds an image name to the array of missing images (above).
* Right now, this is only called from load_additional_images when
* we do not find an image. load_additional_images is called
* before we request all the image names. Thus, request_missing_images
* is called before we send the SEND_IMAGE_NAMES request to the
* server.
*/
void add_missing_image_name(char *buf)
{
strcpy(missing_faces[num_missing_faces++],buf);
}
/* This gets all the image names from the server. It then
* compares it against the list it read in. Any images the
* server has but the client does not are then requested.
*/
void get_image_names(char *buf)
{
char *cp;
do {
if ((cp = strchr(buf,' '))!=NULL) *cp++='\0';
if (!strcmp(buf,"START")) {
num_missing_faces=0;
on_face_num=0;
}
else if (!strcmp(buf,"END")) {
int i;
for (i=0; i<num_missing_faces; i++)
printf("missing face %s\n", missing_faces[i]);
}
else {
if (FindFace(buf,-1)==-1) {
strcpy(missing_faces[num_missing_faces++],buf);
if (num_missing_faces==MAX_MISSING_FACES) {
fprintf(stderr,"Error - too many missing faces.\n");
exit(1);
}
}
}
buf = cp;
} while (buf!=NULL);
}
/* This functions makes the preliminary/startup requests to the
* server.
*/
void init_client_requests()
{
int timeout=5000000,got_input;
/* Init states. Using an enumeration has the advantage that
* a new state can be added between other states with very little
* difficulty. _R_ stands for _Request_ - just an abbreviation
* to make things easier.
*/
enum {Request_Image1, Request_Image_Names,
Request_Image2, Request_Arch_Names, Request_Archs, Finished}
init_state=Request_Image1;
while (init_state!=Finished) {
got_input=command_loop(timeout);
/* init_state is what stage of initialization we are on.
* during this phase, we have very long timeouts (5 seconds,
* but this is an arbitrary number). If we haven't gotten
* any data in that time, we go to the next state.
* Unfortunately, this makes for a bit longer startup time.
*
* note that the init states are meant to break through -
* thus it could go from state 1 to 5 without ever doing
* a read if none of those states does anything (due
* to command line options or other reasons
* Thus, all init_state checks should be in order that they
* are defined in the enumeration type.
*/
/* First image request stage - this requests images that were
* missing during the load_additional_image function call.
* Only give so much time for the server to send us the
* imagess - otherwise, we would never leave the loop.
* (perhaps not make the error fatal?)
*/
if (init_state==Request_Image1) {
static int retries=0;
if (request_missing_images(5)) {
if (!got_input) {
if (++retries>MAX_RETRIES) {
LOG(llevError,"Exceeded retries on requesting images.\n");
exit(1);
}
}
else retries=0;
continue;
}
else init_state++;
}
/* Request the image names. Only make the request if the
* player has invoked us with the right options (init_load_image
* is true.) In either case, go to the next state
*/
if (init_state==Request_Image_Names) {
init_state++;
if (init_load_image) {
write_socket("SEND_IMAGE_NAMES\n");
continue; /* So that we will read in the response */
}
}
/* Request missing images that we found about about
* from the SEND_IMAGE_NAMES request (above). There will be
* no images to request in this stage if we did not
* send a SEND_IMAGE_NAME request.
* Otherwise, this code is the same as that in the Request_Image1
* stage.
*/
if (init_state==Request_Image2) {
static int retries=0;
if (request_missing_images(5)) {
if (!got_input) {
if (++retries>MAX_RETRIES) {
LOG(llevError,"Exceeded retries on requesting images.\n");
exit(1);
}
}
else retries=0;
continue;
}
else init_state++;
}
/* This is like the request for image names, but
* is the archetype names instead.
*/
if (init_state==Request_Arch_Names) {
init_state++;
if (init_load_arch) {
write_socket("SEND_IMAGE_ARCH\n");
continue; /* So that we will read in the response */
}
}
/* Now we go through and request the archetyps we are missing.
* Same thing as the requesting the images above.
*/
if (init_state==Request_Archs) {
static int retries=0;
if (request_missing_archs(5)) {
if (!got_input) {
if (++retries>MAX_RETRIES) {
LOG(llevError,"Exceeded retries on requesting images.\n");
exit(1);
}
}
else retries=0;
continue;
}
else init_state++;
}
}
}
#endif
void init_client_vars()
{
int i;
client_libdir=getenv("CFCLIENT_LIBDIR");
#ifdef CLIENT_LIBDIR
if (client_libdir==NULL)
client_libdir=CLIENT_LIBDIR;
#endif
client_archfile = getenv("CFCLIENT_ARCHFILE");
#ifdef CLIENT_ARCHFILE
if (client_archfile==NULL)
client_archfile=CLIENT_ARCHFILE;
#endif
cpl.count_left = 0;
cpl.container = NULL;
cpl.show_what = 0;
memset(&cpl.stats,0, sizeof(Stats));
cpl.stats.maxsp=1; /* avoid div by 0 errors */
cpl.stats.maxhp=1; /* ditto */
cpl.stats.maxgrace=1; /* ditto */
/* ditto - displayed weapon speed is weapon speed/speed */
cpl.stats.speed=1;
cpl.input_text[0]='\0';
cpl.title[0] = '\0';
cpl.range[0] = '\0';
for (i=0; i<range_size; i++)
cpl.ranges[i]=NULL;
cpl.map_x=0;
cpl.map_y=0;
cpl.ob = player_item();
cpl.below = map_item();
}